package com.yzion.baselib.http.interceptor

import com.blankj.utilcode.util.LogUtils
import okhttp3.Interceptor
import okhttp3.MediaType
import okhttp3.Request
import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody
import okio.Buffer
import java.io.IOException

/**
 * 网络日志打印的拦截器
 * 通过：addNetworkInterceptor 设置
 */
class LogInterceptor : Interceptor {

    @Throws(IOException::class)
    override fun intercept(chain: Interceptor.Chain): Response {
        val request: Request = chain.request()
        logRequest(request)
        val response: Response = chain.proceed(request)
        return logResponse(response)
    }

    private fun logRequest(request: Request) {
        val url = request.url.toString()
        val headers = request.headers
        LogUtils.d("method:" + request.method + "|url:" + url)
        if (headers.size > 0) {
            LogUtils.d("headers:\n$headers")
        }
        val requestBody = request.body
        try {
            if (requestBody != null) {
                val mediaType = requestBody.contentType()
                if (mediaType != null) {
                    if (isText(mediaType)) {
                        LogUtils.d(url + " -> params:" + bodyToString(request))
                    } else {
                        LogUtils.d("params:" + "maybe [file part] , too large too print , ignored!")
                    }
                }
            } else {
                LogUtils.d("$url -> request:body is null")
            }
        } catch (e: Exception) {
            e.printStackTrace()
            LogUtils.d(url + " -> exception:" + e.message)
        }
    }

    private fun logResponse(response: Response): Response {
        var body = response.body
        val url = response.request.url.toString()
        try {
            if (body != null) {
                val mediaType = body.contentType()
                if (mediaType != null) {
                    if (isText(mediaType)) {
                        val resp = body.string()
                        LogUtils.d("$url -> response:$resp")
                        body = resp.toResponseBody(body.contentType())
                        return response.newBuilder().body(body).build()
                    } else {
                        LogUtils.d("data:" + "maybe [file part] , too large too print , ignored!")
                    }
                } else {
                    val resp = body.string()
                    LogUtils.d("$url -> mediaType is null | response:$resp")
                    body = resp.toResponseBody(body.contentType())
                    return response.newBuilder().body(body).build()
                }
            } else {
                LogUtils.d("$url -> response:body is null")
            }
        } catch (e: Exception) {
            e.printStackTrace()
            LogUtils.d(url + " -> exception:" + e.message)
        }

        return response
    }

    private fun isText(mediaType: MediaType?): Boolean {
        return if (mediaType == null) false else "text" == mediaType.subtype || "json" == mediaType.subtype || "xml" == mediaType.subtype || "html" == mediaType.subtype || "webviewhtml" == mediaType.subtype || "x-www-form-urlencoded" == mediaType.subtype
    }

    private fun bodyToString(request: Request): String {
        return try {
            val copy = request.newBuilder().build()
            val buffer = Buffer()
            copy.body!!.writeTo(buffer)
            buffer.readUtf8()
        } catch (e: Exception) {
            "something error when show requestBody:" + e.message
        }
    }
}